﻿/**
 * This library is a thing to realize D2L and DI and AOP on Flex2(ActionScript3).
 * Copyright (C) 2007 Takamasa Seki
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * 
 * Contributor : Takamasa Seki(takanafu@gmail.com)
 *               http://www.takanafu.com/
 */

package com.takanafu.haruframework.d2l{
	import com.takanafu.core.haru_internal;
	import com.takanafu.haruframework.aop.Advisor;
	import com.takanafu.haruframework.aop.support.AbstractPointcutAdvisor;
	import com.takanafu.haruframework.aop.support.RegexpMethodPointcutAdvisor;
	import com.takanafu.haruframework.d2l.invoker.IInvocationProxy;
	
	import flash.net.getClassByAlias;
	import flash.utils.getDefinitionByName;
	import flash.utils.getQualifiedClassName;
	import flash.utils.getQualifiedSuperclassName;
	import flash.xml.XMLNode;
	
	import mx.controls.RadioButton;
	import mx.core.Application;
	import mx.core.IUID;
	import mx.core.Singleton;
	import mx.core.UIComponent;
	import mx.core.UIComponentDescriptor;
	import mx.core.mx_internal;
	import mx.managers.SystemManager;
	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.http.HTTPService;
	
	use namespace haru_internal;
	
	public class HaRu{
		haru_internal static var delegateClassMap:Object;
		private static var _appContextData:XML;
		private static var _HaRuManager:IHaRuManager;
		private static var _registed:Boolean = false;
		//private static var _initCallbackComponent:Array = [];
		
		// スコープ変更 20070716
	    public static function get HaRuManager():IHaRuManager{
	    	// エラー原因推測追加 20070831
	    	if(_HaRuManager == null){
	  			trace("![HaRu HaRu::HaRuManager]HaRuManagerが初期化されていません。-include-librariesにてリンクされていない可能性があります。");
	  		}
	        return _HaRuManager;
	    }
	    haru_internal static function set HaRuManager(manager:IHaRuManager):void{
	        _HaRuManager = manager;
	    }
	    
	    haru_internal static function get appContextData():XML{
	        return _appContextData;
	    }
	    haru_internal static function set appContextData(xml:XML):void{
	        _appContextData = xml;
	    }
	    
		haru_internal static function registBeans():void{
			if(_appContextData == null){
				return;
			}
			if(_registed == true){
				return;
			}
			var ivc:IInvocationProxy = Singleton.getInstance("com.takanafu.haruframework.d2l.invoker::IInvocationProxy") as IInvocationProxy;
			
			for each(var prop:XML in _appContextData..beans.bean){
				var clsName:String = prop.attribute("class").toString();
				var cls:Class = HaRuManager.rootSystemManager.getDefinitionByName(clsName) as Class;
				
				//クラスが取得できない場合にはレジストしないように変更 20070816
				if(cls != null){
					ivc.registBean(prop,cls);
				}else{
					trace("![HaRu HaRu::registBeans]クラスが見つかりません。クラス名["+clsName+"]Bean定義の名称が間違っているか、クラスが存在していない可能性があります。");
				}
			}
			_registed = true;
		}
		
		haru_internal static function registPointcutAdvisor():void{
			if(_appContextData == null){
				return;
			}

			var ivc:IInvocationProxy = Singleton.getInstance("com.takanafu.haruframework.d2l.invoker::IInvocationProxy") as IInvocationProxy;
			
			ivc.registPointcutAdvisor();
		}
		
		haru_internal static function registDelegateDesc(desc:UIComponentDescriptor,parent:Array):void{
			var obj:Object = desc.properties as Object;
			var ary:Array = obj.childDescriptors as Array;
			
			if(ary != null){
				parseDescripter(ary,parent);
			}
		}
		
		private static function parseDescripter(ary:Array,parent:Array):void{
			var cnt:Number = ary != null ? ary.length : 0;
			
			for(var i:Number = 0;i < cnt;i++){
				var child:UIComponentDescriptor = ary[i] as UIComponentDescriptor;
				
				if(child != null){
					var id:String = child.id;

					if(id != null){
						var node:XML = findComponentNode(id);
						
						if(node != null){
							for each(var prop:XML in node.listeners.event){
								var ary2:Array = String(prop.@ref).split("::");
								var bean:XML = findBeanNode(ary2[0]);
								
								if(bean != null){
									var ivc:IInvocationProxy = Singleton.getInstance("com.takanafu.haruframework.d2l.invoker::IInvocationProxy") as IInvocationProxy;
									//クラスが取得できない場合にはレジストしないように変更 20070816
									var clsName:String = bean.attribute("class").toString();
									var cls:Class = HaRuManager.rootSystemManager.getDefinitionByName(clsName) as Class;
									
									if(cls != null){
										child = ivc.registInvocationHandler(child,prop,bean,cls,ary2[1],prop.@id);
									}else{
										trace("![HaRu HaRu::parseDescripter]クラスが見つかりません。クラス名["+clsName+"]Bean定義の名称が間違っているか、クラスが存在していない可能性があります。");
									}
								}
							}
						}
						parent.push(id);
					}
					var obj:Object = child.properties as Object;
					var tmp:Array = obj.childDescriptors as Array;
					
					if(tmp != null){
						parseDescripter(tmp,parent);
					}
				}
			}
		}
		
		haru_internal static function registApplicationDelegate(app:Application):void{
			if(_appContextData == null){
				return;
			}
			if(delegateClassMap == null){
				delegateClassMap = {};
			}
			
			var uid:String = app.uid;
			
			if(delegateClassMap[uid]){
				return;
			}
			delegateClassMap[uid] = "registed";
			
			if(app != null){
				var node:XML = findApplicationNode(app.id);
				
				if(node != null){
					for each(var prop:XML in node.listeners.event){
						var ary:Array = String(prop.@ref).split("::");
						var bean:XML = findBeanNode(ary[0]);
						
						if(bean != null){
							var ivc:IInvocationProxy = Singleton.getInstance("com.takanafu.haruframework.d2l.invoker::IInvocationProxy") as IInvocationProxy;
							//クラスが取得できない場合にはレジストしないように変更 20070816
							var clsName:String = bean.attribute("class").toString();
							var cls:Class = HaRuManager.rootSystemManager.getDefinitionByName(clsName) as Class;
							
							if(cls != null){
								ivc.addInvocationHandler(app,prop,bean,cls,ary[1],prop.@id);
							}else{
								trace("![HaRu HaRu::registApplicationDelegate]クラスが見つかりません。クラス名["+clsName+"]Bean定義の名称が間違っているか、クラスが存在していない可能性があります。");
							}
						}
					}
				}
			}
		}
			    
	    private static function findApplicationNode(id:String):XML{
			for each(var prop:XML in _appContextData..Application){
				if(prop.@id == id){
					return prop;
				}
			}
			return null;
		}

	    private static function findComponentNode(id:String):XML{
			for each(var prop:XML in _appContextData..Component){
				if(prop.@id == id){
					return prop;
				}
			}
			return null;
		}
		
		private static function findBeanNode(id:String):XML{
			for each(var prop:XML in _appContextData..beans.bean){
				if(prop.@id == id){
					return prop;
				}
			}
			return null;
		}
	}
}